home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / migd / migPdev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-05  |  28.9 KB  |  1,129 lines

  1. /* 
  2.  * migPdev.c --
  3.  *
  4.  *    Routines to manage pseudo-devices for the migration daemon.
  5.  *    This is also the only file that deals with byte ordering issues.
  6.  *
  7.  *    Most operations are done using ioctls.  Reads and writes are used
  8.  *     for the following purpose:
  9.  *
  10.  *    - the loadavg daemons write load vectors asynchronously,
  11.  *    - user processes can read load vectors for their own host
  12.  *      (synchronously), and
  13.  *    - user processes can select on the pdev to find out about changes
  14.  *      in the state of idle hosts (new ones available or ones being
  15.  *      reclaimed).
  16.  *
  17.  * Copyright 1989, 1990 Regents of the University of California
  18.  * Permission to use, copy, modify, and distribute this
  19.  * software and its documentation for any purpose and without
  20.  * fee is hereby granted, provided that the above copyright
  21.  * notice appear in all copies.  The University of California
  22.  * makes no representations about the suitability of this
  23.  * software for any purpose.  It is provided "as is" without
  24.  * express or implied warranty.
  25.  */
  26.  
  27. #ifndef lint
  28. static char rcsid[] = "$Header: /sprite/src/daemons/migd/RCS/migPdev.c,v 2.1 90/07/05 13:19:38 douglis Exp $ SPRITE (Berkeley)";
  29. #endif /* not lint */
  30.  
  31. #include <sprite.h>
  32. #include <string.h>
  33. #include <errno.h>
  34. #include <status.h>
  35. #include "syslog.h"
  36. #include <bstring.h>
  37. #include <fs.h>
  38. #include <kernel/fs.h>
  39. #include <sys/types.h>
  40. #include <unistd.h>
  41. #include <stdlib.h>
  42. #include <stdio.h>
  43. #include <sys/dir.h>
  44. #include <sys/stat.h>
  45. #include <host.h>
  46. #include <pdev.h>
  47. #include <fmt.h>
  48. #include "migd.h"
  49. #include "migPdev.h"
  50. #include "global.h"
  51.  
  52.  
  53. static int        PdevOpen(), PdevClose(), PdevWrite();
  54. static int        PdevRead(), PdevIoctl();
  55.  
  56. static Pdev_CallBacks    service = {
  57.                 PdevOpen,    /* open */
  58.                 PdevRead,    /* read */
  59.                 PdevWrite,    /* write */
  60.                 PdevIoctl,    /* ioctl */
  61.                 PdevClose,    /* close */
  62.                 NULL, NULL    /* get/set attr */
  63.             };
  64.  
  65. typedef struct {
  66.     int (*routine)();        /* routine to call */
  67.     char *inFmt;        /* string to pass to Fmt_Convert for input */
  68.     char *outFmt;        /* string to pass to Fmt_Convert for output */
  69. } IoctlCallback;
  70.  
  71.     
  72. /*
  73.  * Define fmt conversions for the structures in mig.h.  This is only used
  74.  * here and is separated from the structures because users need not be
  75.  * aware of conversion issues.
  76.  *                                    *
  77.  ********************************************************************
  78.  *                   IMPORTANT NOTE                 *
  79.  ********************************************************************
  80.  *                                    *
  81.  * Changes to the structures in mig.h must also be reflected below. *
  82.  *                                    *
  83.  ********************************************************************
  84.  */
  85.  
  86. /*
  87.  * The Mig_LoadVector is imbedded in a Mig_Info.  With old compilers
  88.  * we can't concatenate anyway.
  89.  */
  90. #define MIGD_LOADVEC_FMT "{w8d3}"
  91. #define MIGD_INFO_FMT "{w12{w8d3}}"
  92. #define MIGD_UP_IN_FMT MIGD_INFO_FMT
  93.  
  94. #define MIGD_GETINFO_IN_FMT "{w2}"
  95. #ifdef __STDC__
  96. #define MIGD_GETINFO_OUT_FMT "w2" MIGD_INFO_FMT "*"
  97. #else /* __STDC__ */
  98. #define MIGD_GETINFO_OUT_FMT "w2{w12{w8d3}}*"
  99. #endif /* __STDC__ */
  100.  
  101.  
  102. #define MIGD_GETIDLE_IN_FMT "{w4}"
  103. #define MIGD_GETIDLE_OUT_FMT "w*"
  104.  
  105.  
  106.  
  107. #define MIGD_DONE_IN_FMT "w*"
  108. #define MIGD_REMOVE_IN_FMT MIGD_DONE_IN_FMT
  109.  
  110. #define MIGD_CHANGE_IN_FMT "w"
  111. #define MIGD_PARAMS_FMT "{w4d2}"
  112. #define MIGD_STATS_FMT "{w12{b12w45{w20}2}8}"
  113. #define MIGD_GET_UPDATE_OUT_FMT "w"
  114. #define MIGD_EVICT_OUT_FMT "w"
  115.  
  116. /* 
  117.  * When a  daemon starts up, it does an ioctl with a full Mig_Info to
  118.  * start things off.  Then it does writes with new load vectors, and
  119.  * ioctls to flag special cases such as eviction.
  120.  */
  121. #define MIGD_DAEMON_IN_FMT MIGD_INFO_FMT
  122.  
  123. static IoctlCallback ioctlCallbacks[] = {
  124.     { Global_GetLoadInfo,     MIGD_GETINFO_IN_FMT, MIGD_GETINFO_OUT_FMT}, 
  125.     { Global_GetIdle,         MIGD_GETIDLE_IN_FMT, MIGD_GETIDLE_OUT_FMT}, 
  126.     { Global_DoneIoctl,        MIGD_DONE_IN_FMT, (char *) NULL}, 
  127.     { Global_RemoveHost,     MIGD_REMOVE_IN_FMT, (char *) NULL},
  128.     { Global_HostUp,         MIGD_UP_IN_FMT, (char *) NULL},
  129.     { Global_ChangeState,    MIGD_CHANGE_IN_FMT, (char *) NULL},
  130.     { Migd_GetParms,        (char *) NULL, MIGD_PARAMS_FMT},
  131.     { Migd_SetParms,        MIGD_PARAMS_FMT, (char *) NULL},
  132.     { Global_GetStats,        (char *) NULL, MIGD_STATS_FMT},
  133.     { Global_GetUpdate,        (char *) NULL, MIGD_GET_UPDATE_OUT_FMT},
  134.     { Migd_EvictIoctl,        (char *) NULL, MIGD_EVICT_OUT_FMT},
  135.     { Global_ResetStats,    (char *) NULL, (char *) NULL},
  136. };
  137.  
  138. /*
  139.  * Pdev identifier for the master end of the pdev, when open.
  140.  */
  141. static Pdev_Token    pdev = (Pdev_Token) NULL;
  142.  
  143. static char *pdevName;            /* File name of the pdev. */ 
  144.  
  145. static int nextOpenID = 0;        /* Identifier for next pdev
  146.                        open by a client. */
  147.  
  148.  
  149.  
  150. List_Links openStreamListHdr;     /* List of open pdevs. */
  151. List_Links *openStreamList;     /* Pointer to list, used in calls. */
  152.  
  153. int migPdev_Debug = 0;
  154.  
  155.  
  156.  
  157.  
  158. /*
  159.  *----------------------------------------------------------------------
  160.  *
  161.  * MigPdev_Init --
  162.  *
  163.  *    Initialize data structures for this module.
  164.  *
  165.  * Results:
  166.  *    None.
  167.  *
  168.  * Side effects:
  169.  *    Open stream list is set up.
  170.  *
  171.  *----------------------------------------------------------------------
  172.  */
  173.  
  174. void
  175. MigPdev_Init()
  176. {
  177.  
  178.     openStreamList = &openStreamListHdr;
  179.     List_Init(openStreamList);
  180.     if (migPdev_Debug > 5) {
  181.     pdev_Trace = 1;
  182.     }
  183. }
  184.     
  185.  
  186. /*
  187.  *----------------------------------------------------------------------
  188.  *
  189.  * MigPdev_OpenMaster --
  190.  *
  191.  *    Set up the master end of a pseudo-device.  This can be either
  192.  *     the host-specific pdev or the global pdev, as specified by the
  193.  *    global variable migd_GlobalMaster.
  194.  *
  195.  * Results:
  196.  *    0 for successful completion, -1 for error.
  197.  *
  198.  * Side effects:
  199.  *    Opens pseudo-device as master.
  200.  *
  201.  *----------------------------------------------------------------------
  202.  */
  203.  
  204. int
  205. MigPdev_OpenMaster()
  206. {
  207.     struct stat atts;
  208.     
  209.     if (migPdev_Debug > 1) {
  210.     PRINT_PID;
  211.     fprintf(stderr, "MigPdev_OpenMaster -\n");
  212.     }
  213.  
  214.     if (migd_GlobalMaster) {
  215.     pdevName = migd_GlobalPdevName;
  216.     } else {
  217.     pdevName = migd_LocalPdevName;
  218.     }
  219.     
  220.     /*
  221.      * Open pdev.  If it's the global pdev and we can't open it, then
  222.      * presumably someone else beat us to it.  That's fine, let
  223.      * him handle it.  In any case, punt the error to our caller.
  224.      */
  225.     if (migPdev_Debug > 2) {
  226.     PRINT_PID;
  227.     fprintf(stderr, "MigPdev_OpenMaster - Open %s\n", pdevName);
  228.     }
  229. #ifdef notdef
  230.     pdev_Trace = 0;
  231. #endif
  232.     /*
  233.      * If we're opening the local pdev, and we've gotten this far, we
  234.      * know the global master recognizes us as the only daemon on this
  235.      * host.  Therefore, ensure against leftover masters by removing the
  236.      * pdev in case it already exists.  Note that statting the file
  237.      * may result in an error even though it actually exists, due to
  238.      * trying to get attributes associated with a nonexistent pdev master.
  239.      */
  240.     if (!migd_GlobalMaster) {
  241.     if (migPdev_Debug > 0 && stat(pdevName, &atts) == 0) {
  242.         fprintf(stderr, "Warning: removing leftover pdev %s.\n",
  243.            pdevName);
  244.     }
  245.     (void) unlink(pdevName);
  246.     }
  247.     pdev = Pdev_Open(pdevName, NULL, 0, 0, &service, NULL);
  248.     if (pdev == NULL) {
  249.     if (migPdev_Debug > 0) {
  250.         PRINT_PID;
  251.         fprintf(stderr, "MigPdev_OpenMaster: %s\n", pdev_ErrorMsg);
  252.     }
  253.     errno = ENODEV;
  254.     return (-1);
  255.     }
  256.  
  257.     if (migPdev_Debug > 1) {
  258.     PRINT_PID;
  259.     fprintf(stderr, "MigPdev_OpenMaster - completed successfully\n");
  260.     }
  261.  
  262.     return (0);
  263. }
  264.  
  265.  
  266. /*
  267.  *----------------------------------------------------------------------
  268.  *
  269.  * MigPdev_End --
  270.  *
  271.  *    Terminate service of the master end of the pdev.
  272.  *
  273.  * Results:
  274.  *    None.
  275.  *
  276.  * Side effects:
  277.  *    The pdev is removed and closed.
  278.  *
  279.  *----------------------------------------------------------------------
  280.  */
  281.  
  282. void
  283. MigPdev_End()
  284. {
  285.     int status;
  286.  
  287.     if (migPdev_Debug > 2) {
  288.     PRINT_PID;
  289.     fprintf(stderr, "MigPdev_End -\n");
  290.     }
  291.  
  292.     Pdev_Close(pdev);
  293.     pdev = NULL;
  294.  
  295.     status = unlink(pdevName);
  296.     if (status == -1) {
  297.     SYSLOG2(LOG_WARNING, "couldn't remove %s: %s\n",
  298.            pdevName, strerror(errno));
  299.     }
  300. }
  301.  
  302.  
  303. /*
  304.  *----------------------------------------------------------------------
  305.  *
  306.  * MigPdev_Stat --
  307.  *
  308.  *    Perform an fstat on the descriptor associated with the pdev we
  309.  *     are controlling.  .... OBSOLETE (never used)
  310.  *
  311.  * Results:
  312.  *    On error, -1 is returned and errno is set to the error returned
  313.  *    by fstat; else 0 is returned.
  314.  *
  315.  * Side effects:
  316.  *    None.
  317.  *
  318.  *----------------------------------------------------------------------
  319.  */
  320.  
  321. #ifdef 0 
  322. int
  323. MigPdev_Stat(attsPtr)
  324.     struct stat *attsPtr;
  325. {
  326.     int stream = Pdev_GetStreamID(pdev);
  327.     
  328.     if (migPdev_Debug > 2) {
  329.     PRINT_PID;
  330.     fprintf(stderr, "MigPdev_Stat -\n");
  331.     }
  332.     return(fstat(stream, attsPtr));
  333. }
  334. #endif
  335.  
  336.  
  337. /*
  338.  *----------------------------------------------------------------------
  339.  *
  340.  * SendSignal --
  341.  *
  342.  *    Send a signal over a stream.  Only used for signalling other
  343.  *    daemons upon normal master termination (for debugging).
  344.  *
  345.  * Results:
  346.  *    0 is returned, since we don't want to stop partway through.
  347.  *
  348.  * Side effects:
  349.  *    None.
  350.  *
  351.  *----------------------------------------------------------------------
  352.  */
  353.  
  354.  
  355. static int 
  356. SendSignal(streamPtr, clientData)
  357.     Pdev_Stream *streamPtr;    /* Pdev stream, containing streamID */
  358.     ClientData clientData;    /* Signal to send, as a ClientData */
  359. {
  360. #ifdef USE_PDEV_SIGNALS
  361.     Pdev_Signal sig;
  362. #endif /* USE_PDEV_SIGNALS */
  363.     int status;
  364.     Migd_OpenStreamInfo *cltPtr =
  365.     (Migd_OpenStreamInfo *) streamPtr->clientData;
  366.  
  367.     if (cltPtr->type != MIGD_DAEMON) {
  368.     return(0);
  369.     }
  370.     if (migPdev_Debug > 3) {
  371.     PRINT_PID;
  372.     fprintf(stderr, "SendSignal - sending signal to process %x\n",
  373.            cltPtr->processID);
  374.     }
  375.  
  376. #ifdef USE_PDEV_SIGNALS
  377.     sig.signal = (unsigned int) clientData;
  378.     sig.code = 0;
  379.     status = Fs_IOControl(streamPtr->streamID, IOC_PDEV_SIGNAL_OWNER,
  380.             sizeof(Pdev_Signal), (char *) &sig, 0, (char *) NULL);
  381. #else /* USE_PDEV_SIGNALS */
  382.     status = Sig_Send((unsigned int) clientData, cltPtr->processID, 0);
  383. #endif /* USE_PDEV_SIGNALS */
  384.     if (status != SUCCESS && migPdev_Debug > 0) {
  385.     PRINT_PID;
  386.     fprintf(stderr, "SendSignal: error sending signal to process %x: %s\n",
  387.            cltPtr->processID, Stat_GetMsg(status));
  388.     }
  389.     return(0);
  390. }
  391.  
  392.  
  393. /*
  394.  *----------------------------------------------------------------------
  395.  *
  396.  * MigPdev_SignalClients --
  397.  *
  398.  *    Send a signal to all clients.
  399.  *
  400.  * Results:
  401.  *    None.
  402.  *
  403.  * Side effects:
  404.  *    None.
  405.  *
  406.  *----------------------------------------------------------------------
  407.  */
  408.  
  409. void
  410. MigPdev_SignalClients(sig)
  411.     int sig;            /* Signal to send. */
  412. {
  413.     if (migPdev_Debug > 2) {
  414.     PRINT_PID;
  415.     fprintf(stderr, "MigPdev_SignalClients -\n");
  416.     }
  417.  
  418.     (void) Pdev_EnumStreams(pdev, SendSignal, (ClientData) sig);
  419. }
  420.  
  421. /*
  422.  *----------------------------------------------------------------------
  423.  *
  424.  * MigPdev_MakeReady --
  425.  *
  426.  *    Make a pdev stream readable, so someone selecting on it
  427.  *    will know to do an ioctl.  The ClientData is either NULL or
  428.  *    a function to determine whether to make this stream selectable.
  429.  *
  430.  * Results:
  431.  *    If an error occurs during the ioctl, then that error is returned,
  432.  *    else 0.
  433.  *
  434.  * Side effects:
  435.  *    The stream is marked.
  436.  *
  437.  *----------------------------------------------------------------------
  438.  */
  439.  
  440.  
  441. int 
  442. MigPdev_MakeReady(streamPtr, clientData)
  443.     Pdev_Stream *streamPtr;    /* Pdev stream, containing streamID */
  444.     ClientData clientData;    /* A function for selection, or NULL. */
  445. {
  446.     int (*func)();
  447.     int status;
  448.     Migd_OpenStreamInfo *cltPtr = (Migd_OpenStreamInfo *) streamPtr->clientData;
  449.  
  450.     func = (int (*) ()) clientData;
  451.     if (func != (int (*) ()) NULL) {
  452.     if (!(*func)(cltPtr)) {
  453.         return(0);
  454.     }
  455.     }
  456.     cltPtr->defaultSelBits |= FS_READ;
  457.     status = Fs_IOControl(streamPtr->streamID, IOC_PDEV_READY, sizeof(int),
  458.             (char *) &cltPtr->defaultSelBits, 0, (char *) NULL);
  459.     /*
  460.      * Note any errors, but only return non-zero status if we had
  461.      * no selection function (hence were notifying a particular
  462.      * client rather than a bunch at once).
  463.      */
  464.     if (status != 0) {
  465.     if (migPdev_Debug > 0) {
  466.         PRINT_PID;
  467.         fprintf(stderr, "Error making stream selectable for client %x: %s\n",
  468.            cltPtr->processID, Stat_GetMsg(status));
  469.     }
  470.     if (func != (int (*) ()) NULL) {
  471.         return(0);
  472.     }
  473.     return(status);
  474.     }
  475.     return(0);
  476. }
  477.  
  478.  
  479. /*
  480.  *----------------------------------------------------------------------
  481.  *
  482.  * DaemonSelectPredicate --
  483.  *
  484.  *    Selection predicate to just get clients that are daemons.
  485.  *
  486.  * Results:
  487.  *    1 if a daemon, 0 otherwise.
  488.  *
  489.  * Side effects:
  490.  *    None.
  491.  *
  492.  *----------------------------------------------------------------------
  493.  */
  494.  
  495. static int
  496. DaemonSelectPredicate(cltPtr)
  497.     Migd_OpenStreamInfo *cltPtr;
  498. {
  499.     if (cltPtr->type == MIGD_DAEMON) {
  500.     return(Global_IsHostUp(cltPtr->host));
  501.     } else {
  502.     return(0);
  503.     }
  504. }
  505.  
  506. /*
  507.  *----------------------------------------------------------------------
  508.  *
  509.  * MigPdev_NotifyDaemons --
  510.  *
  511.  *    Make migration daemons exceptable.  (To notify a particular
  512.  *    client, use MigPdev_MakeReady directly).
  513.  *
  514.  * Results:
  515.  *    None.
  516.  *
  517.  * Side effects:
  518.  *    None.
  519.  *
  520.  *----------------------------------------------------------------------
  521.  */
  522.  
  523. void
  524. MigPdev_NotifyDaemons()
  525. {
  526.  
  527.     if (migPdev_Debug > 2) {
  528.     PRINT_PID;
  529.     fprintf(stderr, "MigPdev_NotifyDaemons -\n");
  530.     }
  531.  
  532.     (void) Pdev_EnumStreams(pdev, MigPdev_MakeReady,
  533.                 (ClientData) DaemonSelectPredicate);
  534. }
  535.  
  536. /*
  537.  *----------------------------------------------------------------------
  538.  *
  539.  * PdevOpen --
  540.  *
  541.  *    Service an open request for the pdev.
  542.  *
  543.  * Results:
  544.  *    0, or an error condition.
  545.  *
  546.  * Side effects:
  547.  *    None.
  548.  *
  549.  *----------------------------------------------------------------------
  550.  */
  551.  
  552. /* ARGSUSED */
  553. static int
  554. PdevOpen(data, streamPtr, buff, flags, processID, host, user, selPtr)
  555.     ClientData data;        /* Ignored. */
  556.     Pdev_Stream *streamPtr;    /* Information for the stream. */
  557.     char *buff;            /* Ignored */
  558.     int flags;            /* Flags passed to Fs_Open. */
  559.     int processID;        /* Id of process doing open. */
  560.     int host;            /* Host on which opened. */
  561.     int user;            /* Userid of opener. */
  562.     int *selPtr;        /* Bits for Fs_Select. */
  563. {
  564.     Migd_OpenStreamInfo *cltPtr;
  565.  
  566.     if (migPdev_Debug > 2) {
  567.     PRINT_PID;
  568.     fprintf(stderr, "PdevOpen - request from %d:%x\n", host, processID);
  569.     }
  570.  
  571.     if (migd_Quit) {
  572.     if (migPdev_Debug > 0) {
  573.         PRINT_PID;
  574.         fprintf(stderr,
  575.            "PdevOpen - can't handle request from %d:%x because we are shutting down.\n",
  576.            host, processID);
  577.     }
  578.     return(ESHUTDOWN);
  579.     }
  580.     
  581.     /* Check valid open flags */
  582.     flags &= FS_USER_FLAGS;
  583.     if (flags & ~(FS_WRITE | FS_READ)) {
  584.     if (migPdev_Debug > 0) {
  585.         PRINT_PID;
  586.         fprintf(stderr, "PdevOpen - bad flags %x\n", flags);
  587.     }
  588.     return(EACCES);
  589.     }
  590.  
  591.     cltPtr = mnew(Migd_OpenStreamInfo);
  592.     bzero((char *) cltPtr, sizeof(Migd_OpenStreamInfo));
  593.     cltPtr->streamPtr = streamPtr;
  594.     cltPtr->user = user;
  595.     cltPtr->host = host;
  596.     cltPtr->processID = processID;
  597.     cltPtr->openID = nextOpenID;
  598.     /*
  599.      * By default, processes can't read or write the pdev, they must
  600.      * use ioctls.  They can use an ioctl to register a long-term
  601.      * interest, such as if they're a loadavg daemon or a load widget,
  602.      * but until then the default is not to be able to select on this
  603.      * stream.  (In addition, they can select on the stream and be
  604.      * told it's readable if there's a change in status, but again,
  605.      * it's unreadable by default until that happens.)  This default
  606.      * value is used to make it easy for routines to reset the select
  607.      * bits as appropriate.
  608.      */
  609.     if (migd_GlobalMaster) {
  610.     cltPtr->defaultSelBits = 0;
  611.     cltPtr->type = ((user == 0) && (flags & FS_WRITE)) ?
  612.         MIGD_DAEMON : MIGD_USER;
  613.     } else {
  614.     cltPtr->defaultSelBits = FS_READ;
  615.     cltPtr->type = MIGD_LOCAL;
  616.     }
  617.     nextOpenID++;
  618.     streamPtr->clientData = (ClientData) cltPtr;
  619.     List_Init(&cltPtr->currentRequests);
  620.     List_Init(&cltPtr->messages);
  621.     List_InitElement(&cltPtr->nextStream);
  622.     List_Insert((List_Links *)cltPtr, LIST_ATREAR(openStreamList));
  623.     cltPtr->waitPtr = (Migd_WaitList *) NULL;
  624.     
  625.     *selPtr = cltPtr->defaultSelBits;
  626.  
  627.     if (migPdev_Debug > 3) {
  628.     PRINT_PID;
  629.     fprintf(stderr, "PdevOpen - returning status 0\n");
  630.     }
  631.  
  632.     return(0);
  633. }
  634.  
  635.  
  636. /*
  637.  *----------------------------------------------------------------------
  638.  *
  639.  * PdevClose --
  640.  *
  641.  *    Service a close request for the pdev.  Clean up state, either
  642.  *     marking a host as down if the daemon on that host closed its
  643.  *    connection, or freeing hosts used by a client if it closes the
  644.  *    connection without freeing them first.
  645.  *
  646.  * Results:
  647.  *    0, or an error condition.
  648.  *
  649.  * Side effects:
  650.  *    None.
  651.  *
  652.  *----------------------------------------------------------------------
  653.  */
  654.  
  655. static int
  656. PdevClose(streamPtr)
  657.     Pdev_Stream *streamPtr;    /* Information for the stream */
  658. {
  659.     Migd_OpenStreamInfo *cltPtr;
  660.  
  661.  
  662.     cltPtr = (Migd_OpenStreamInfo *) streamPtr->clientData;
  663.     if (cltPtr == (Migd_OpenStreamInfo *) NULL) {
  664.     /*
  665.      * Stream wasn't fully opened -- if, for example, we were quitting
  666.      * at the time.
  667.      */
  668.     return(0);
  669.     }
  670.  
  671.     if (migPdev_Debug > 3) {
  672.     PRINT_PID;
  673.     fprintf(stderr, "PdevClose - pid %x\n", cltPtr->processID);
  674.     }
  675.  
  676.     switch (cltPtr->type) {
  677.     case MIGD_DAEMON: {
  678.         if (migPdev_Debug > 1) {
  679.         PRINT_PID;
  680.         fprintf(stderr, "PdevClose - daemon %x on host %d exited\n",
  681.                cltPtr->processID, cltPtr->host);
  682.         }
  683.         (void) Global_HostDown(cltPtr->host, 1);
  684.         break;
  685.     }
  686.     case MIGD_USER: {
  687.         if (migPdev_Debug > 2) {
  688.         PRINT_PID;
  689.         fprintf(stderr, "PdevClose - process closed pdev\n");
  690.         }
  691.         if (migd_GlobalMaster) {
  692.         /*
  693.          * Clean up after the process, by releasing hosts and
  694.          * recording statistics.
  695.          */
  696.         (void) Global_Done(cltPtr, MIG_ALL_HOSTS, 1);
  697.         }
  698.         break;
  699.     }
  700.     case MIGD_CLOSED: 
  701.     case MIGD_NEW: {
  702.         if (migPdev_Debug > 0) {
  703.         PRINT_PID;
  704.         fprintf(stderr,
  705.                "PdevClose - never heard from process %x, or connection is unusable.\n",
  706.                cltPtr->processID);
  707.         }
  708.         break;
  709.     }
  710.     case MIGD_LOCAL: {
  711.         if (migPdev_Debug > 2) {
  712.         PRINT_PID;
  713.         fprintf(stderr,
  714.                "PdevClose - local process %x exited.\n",
  715.                cltPtr->processID);
  716.         }
  717.         break;
  718.     default: {
  719.         PRINT_PID;
  720.         fprintf(stderr,
  721.             "PdevClose - bad type (%d) for client type.\n",
  722.             (int) cltPtr->type);
  723.         }
  724.         break;
  725.     }
  726.     }
  727.     
  728.     List_Remove((List_Links *)cltPtr);
  729.     free((Address) cltPtr);
  730.     return (0);
  731. }
  732.  
  733.  
  734. /*
  735.  *----------------------------------------------------------------------
  736.  *
  737.  * PdevRead --
  738.  *
  739.  *    Service a read request for the pdev.  This is permitted when a
  740.  *    process wants the load vector for its own host, and talks to
  741.  *    its daemon directly.  The master daemon doesn't service read
  742.  *    requests; requests for load go through the ioctl interface, which
  743.  *    also deals with byte swapping.  Note: we don't check the hostID
  744.  *     of the requester, since after all the hostID could be a physical
  745.  *    host that's different from us but the same byte order, but
  746.  *    if someone on a different architecture tries to read our structure
  747.  *    they may get garbage.
  748.  * 
  749.  * Results:
  750.  *    0 for success, EINVAL is returned if we're not the local daemon
  751.  *    or the read isn't at least the size of a Mig_Info structure.  
  752.  *
  753.  * Side effects:
  754.  *    None.
  755.  *
  756.  *----------------------------------------------------------------------
  757.  */
  758. /* ARGSUSED */
  759. static int
  760. PdevRead(streamPtr, readPtr, freeItPtr, selectBitsPtr, sigPtr)
  761.     Pdev_Stream *streamPtr;    /* Service stream the client specified in its
  762.                  * kernel call. */
  763.     Pdev_RWParam *readPtr;    /* Read parameter block.  Indicates size,
  764.                  * buffer, plus various IDs */
  765.     Boolean *freeItPtr;        /* Not used here. */
  766.     int *selectBitsPtr;        /* Store new select state of stream here. */
  767.     Pdev_Signal *sigPtr;    /* Signal information for returning signal. */
  768. {
  769.     Migd_OpenStreamInfo *cltPtr;
  770.  
  771.     cltPtr = (Migd_OpenStreamInfo *) streamPtr->clientData;
  772.     *selectBitsPtr = cltPtr->defaultSelBits;
  773.  
  774.     if (migPdev_Debug > 3) {
  775.     PRINT_PID;
  776.     fprintf(stderr, "PdevRead - request from %d:%x\n",
  777.            cltPtr->host, cltPtr->processID);
  778.     }
  779.     if (migd_Quit) {
  780.     sigPtr->signal = SIG_TERM;
  781.     }
  782.     if (migd_GlobalMaster) {
  783.     /*
  784.      * Wrong interface to communicate with the global master.
  785.      */
  786.     return (EINVAL);
  787.     }
  788.     if (readPtr->length < sizeof(Mig_Info)) {
  789.     if (migPdev_Debug > 0) {
  790.         PRINT_PID;
  791.         fprintf(stderr, "PdevRead - short read from %d:%x\n",
  792.            cltPtr->host, cltPtr->processID);
  793.     }
  794.     return(EINVAL);
  795.     }
  796.  
  797.     Migd_GetLocalLoad(readPtr->buffer);
  798.     readPtr->length = sizeof(Mig_Info);
  799.     return (0);
  800. }
  801.  
  802.  
  803. /*
  804.  *----------------------------------------------------------------------
  805.  *
  806.  * PdevWrite --
  807.  *
  808.  *    Service a write request for the pdev.  Write requests can be from
  809.  *     daemons, telling us a new load vector, or from clients, requesting
  810.  *    or returning one or more hosts.
  811.  *
  812.  * Results:
  813.  *    An error status, or 0 for success, is returned.
  814.  *
  815.  * Side effects:
  816.  *    None.
  817.  *
  818.  *----------------------------------------------------------------------
  819.  */
  820.  
  821. /* ARGSUSED */
  822. static int
  823. PdevWrite(streamPtr, async, writePtr, selectBitsPtr, sigPtr)
  824.     Pdev_Stream *streamPtr;    /* Service stream the client specified in its
  825.                  * kernel call. */
  826.     int async;            /* Non-zero means this is an asynchronous
  827.                  * write request. */
  828.     Pdev_RWParam *writePtr;    /* Write parameter block.  Indicates size,
  829.                  * offset, and buffer, among other things */
  830.     int *selectBitsPtr;        /* Just set to default. */
  831.     Pdev_Signal *sigPtr;    /* Signal to return, if any */
  832. {
  833.     Migd_OpenStreamInfo *cltPtr;
  834.     Mig_LoadVector loadVec;
  835.     Mig_LoadVector *loadPtr;
  836.     int status;
  837.     int inBufSize;
  838.     int outBufSize;
  839.  
  840.     cltPtr = (Migd_OpenStreamInfo *) streamPtr->clientData;
  841.  
  842.     if (migPdev_Debug > 3) {
  843.     PRINT_PID;
  844.     fprintf(stderr, "PdevWrite - packet from %d:%x\n", cltPtr->host,
  845.            cltPtr->processID);
  846.     }
  847.  
  848.     if (migd_Quit) {
  849.     sigPtr->signal = SIG_TERM;
  850.     }
  851.  
  852.     *selectBitsPtr = cltPtr->defaultSelBits;
  853.  
  854.     /*
  855.      * Process packet.
  856.      */
  857.     if (cltPtr->type != MIGD_DAEMON) {
  858.     if (migPdev_Debug > 1) {
  859.         PRINT_PID;
  860.         fprintf(stderr, "PdevWrite - got invalid write from %d:%x\n",
  861.            cltPtr->host, cltPtr->processID);
  862.     }
  863.     return(EPERM);
  864.     }
  865.     if (writePtr->length < sizeof(Mig_LoadVector)) {
  866.     if (migPdev_Debug > 0) {
  867.         SYSLOG3(LOG_WARNING,
  868.             "PdevWrite - short write from process %x: %d bytes of %d\n",
  869.             cltPtr->processID, writePtr->length,
  870.             sizeof(Mig_LoadVector));
  871.     }
  872.     return(EINVAL);
  873.     }
  874.     if (cltPtr->format != FMT_MY_FORMAT) {
  875.     inBufSize = writePtr->length;
  876.     outBufSize = sizeof(Mig_LoadVector);
  877.     status = Fmt_Convert(MIGD_LOADVEC_FMT,
  878.                  cltPtr->format,
  879.                  &inBufSize,
  880.                  writePtr->buffer,
  881.                  FMT_MY_FORMAT,
  882.                  &outBufSize,
  883.                  (char *) &loadVec);
  884.     if (status != FMT_OK || inBufSize != writePtr->length ||
  885.         outBufSize != sizeof(Mig_LoadVector)) {
  886.         PRINT_PID;
  887.         fprintf(stderr,
  888.            "PdevWrite - error swapping Mig_LoadVector structure, status = %d, swapped %d->%d of %d.\n",
  889.            status, inBufSize, outBufSize, sizeof(Mig_LoadVector));
  890.         return(EINVAL);
  891.     }
  892.     loadPtr = &loadVec;
  893.     } else {
  894.     loadPtr = (Mig_LoadVector *) writePtr->buffer;
  895.     }
  896.     status = Global_UpdateLoad(cltPtr, loadPtr);
  897.     if (status == 0 && !async) {
  898.     writePtr->length = sizeof(Mig_LoadVector);
  899.     }
  900.     
  901.     return(status);
  902. }
  903.  
  904.  
  905. /*
  906.  *----------------------------------------------------------------------
  907.  *
  908.  * PdevIoctl --
  909.  *
  910.  *    Basic entry point for communications with a server.  This
  911.  *    routine handles byte-swapping, but the real work is done
  912.  *    elsewhere.
  913.  *
  914.  * Results:
  915.  *    An error status, or 0 for success, is returned.
  916.  *
  917.  * Side effects:
  918.  *    Variable.
  919.  *
  920.  *----------------------------------------------------------------------
  921.  */
  922.  
  923. /* ARGSUSED */
  924. static int
  925. PdevIoctl(streamPtr, ioctlPtr, selectBitsPtr, sigPtr)
  926.     Pdev_Stream *streamPtr;    /* Service stream the client specified in its
  927.                  * kernel call. */
  928.     Pdev_IOCParam *ioctlPtr;    /* I/O control parameters */
  929.     int *selectBitsPtr;        /* Store new select state here. */
  930.     Pdev_Signal *sigPtr;    /* Returned signal, if any */
  931. {
  932.     Migd_OpenStreamInfo *cltPtr;
  933.     int status;
  934.     Address inBuffer;
  935.     Address outBuffer;
  936.     int bufSize;        /* Temporary holder for buffer size passed
  937.                    to Fmt_Convert. */
  938.     int inBufSize;        /* Size of the real input buffer. */
  939.     int outBufSize;        /* Size of the real output buffer. */
  940.     int command;
  941.     char *swapBuffer = NULL;
  942.     IoctlCallback *callbackPtr;
  943.  
  944.     cltPtr = (Migd_OpenStreamInfo *) streamPtr->clientData;
  945.     command = ioctlPtr->command;
  946.  
  947.     if (migPdev_Debug > 3) {
  948.     PRINT_PID;
  949.     fprintf(stderr, "PdevIoctl - command %d from %x\n", command,
  950.            cltPtr->processID);
  951.     }
  952.  
  953.     /*
  954.      * Set the selectBits ptr up front in case we return an error early on.
  955.      */
  956.     *selectBitsPtr = cltPtr->defaultSelBits;
  957.     if (migd_Quit) {
  958.     sigPtr->signal = SIG_TERM;
  959.     }
  960.  
  961.     outBufSize = ioctlPtr->outBufSize;
  962.     inBufSize = ioctlPtr->inBufSize;
  963.  
  964.     if (command == IOC_SET_OWNER) {
  965.     return(0);
  966.     }
  967.     
  968.     if (command <= IOC_GENERIC_LIMIT ||
  969.     command > IOC_MIG_LASTCMD) {
  970.     if (migPdev_Debug > 2) {
  971.         SYSLOG2(LOG_WARNING, "undefined ioctl from %x: %d\n",
  972.             cltPtr->processID, command);
  973.     }
  974.     return(EINVAL);
  975.     }
  976.  
  977.     
  978.  
  979.     callbackPtr = &ioctlCallbacks[command - IOC_GENERIC_LIMIT - 1];
  980.  
  981.     /*
  982.      * We need to swap if we're different byte orders.  We swap right now if
  983.      * this ioctl takes input (inFmt is non-null).  We allocate extra
  984.      * space for swapping later if outFmt is non-null. We save the format away
  985.      * for use in read/write calls.
  986.      */
  987.     cltPtr->format = ioctlPtr->format;
  988.     if (ioctlPtr->format != FMT_MY_FORMAT) {
  989.     if (callbackPtr->inFmt != (char *) NULL) {
  990.         bufSize = inBufSize;
  991.         swapBuffer = Malloc(inBufSize);
  992.         status = Fmt_Convert(callbackPtr->inFmt,
  993.                  ioctlPtr->format,
  994.                  &inBufSize,
  995.                  ioctlPtr->inBuffer,
  996.                  FMT_MY_FORMAT,
  997.                  &bufSize,
  998.                  swapBuffer);
  999.         if (status != FMT_OK || inBufSize != ioctlPtr->inBufSize) {
  1000.         SYSLOG3(LOG_ERR,
  1001.                "PdevIoctl - error swapping ioctl input buffer, status = %d, swapped %d of %d.\n",
  1002.                status, inBufSize, ioctlPtr->inBufSize);
  1003.         free(swapBuffer);
  1004.         return(EINVAL);
  1005.         }
  1006.         inBuffer = swapBuffer;
  1007.         inBufSize = bufSize;
  1008.     } else {
  1009.         inBuffer = ioctlPtr->inBuffer;
  1010.     }
  1011.     if (callbackPtr->outFmt != (char *) NULL) {
  1012.         outBuffer = Malloc(outBufSize);
  1013.     } else {
  1014.         outBuffer = ioctlPtr->outBuffer;
  1015.     }
  1016.     } else {
  1017.     inBuffer = ioctlPtr->inBuffer;
  1018.     outBuffer = ioctlPtr->outBuffer;
  1019.     }
  1020.     
  1021.  
  1022.     status = (*callbackPtr->routine)
  1023.     (cltPtr, ioctlPtr->command, inBuffer, inBufSize, outBuffer,
  1024.      &outBufSize);
  1025.  
  1026. #ifdef lint
  1027.     status = Global_GetLoadInfo(cltPtr, ioctlPtr->command, inBuffer,
  1028.                 inBufSize, outBuffer, &outBufSize);
  1029.     status = Global_GetIdle(cltPtr, ioctlPtr->command, inBuffer, inBufSize,
  1030.                 outBuffer, &outBufSize);
  1031.     status = Global_DoneIoctl(cltPtr, ioctlPtr->command, inBuffer, inBufSize,
  1032.                  outBuffer, &outBufSize);
  1033.     status = Global_RemoveHost(cltPtr, ioctlPtr->command, inBuffer, inBufSize,
  1034.                    outBuffer, &outBufSize);
  1035.     status = Global_HostUp(cltPtr, ioctlPtr->command, inBuffer, inBufSize,
  1036.                    outBuffer, &outBufSize);
  1037.     status = Global_ChangeState(cltPtr, ioctlPtr->command, inBuffer, inBufSize,
  1038.                    outBuffer, &outBufSize);
  1039.     status = Global_GetStats(cltPtr, ioctlPtr->command, inBuffer, inBufSize,
  1040.                    outBuffer, &outBufSize);
  1041. #endif /* lint */
  1042.  
  1043.     if (status == 0) {
  1044.     /*
  1045.      * This time we need to swap if we're different byte orders and if
  1046.      * this ioctl returns output (outFmt is non-null).
  1047.      */
  1048.     if (ioctlPtr->format != FMT_MY_FORMAT &&
  1049.         callbackPtr->outFmt != (char *) NULL) {
  1050.         int origSize;
  1051.         
  1052.         bufSize = outBufSize;
  1053.         origSize = outBufSize;
  1054.         status = Fmt_Convert(callbackPtr->outFmt,
  1055.                  FMT_MY_FORMAT,
  1056.                  &bufSize,
  1057.                  outBuffer,
  1058.                  ioctlPtr->format,
  1059.                  &outBufSize,
  1060.                  ioctlPtr->outBuffer);
  1061.         if (status != FMT_OK || bufSize != origSize) {
  1062.         SYSLOG3(LOG_ERR,
  1063.                "PdevIoctl - error swapping ioctl output buffer, status = %d, swapped %d of %d.\n",
  1064.                status, bufSize, origSize);
  1065.         status = EINVAL;
  1066.         }
  1067.     }
  1068.     }
  1069.     /*
  1070.      * Free up extra buffers.
  1071.      */
  1072.     if (inBuffer != ioctlPtr->inBuffer) {
  1073.     free(inBuffer);
  1074.     }
  1075.     if (outBuffer != ioctlPtr->outBuffer) {
  1076.     free(outBuffer);
  1077.     }
  1078.  
  1079.     /*
  1080.      * Reset the selectBits ptr based on current value.
  1081.      */
  1082.     *selectBitsPtr = cltPtr->defaultSelBits;
  1083.  
  1084.     /*
  1085.      * Return a unix status since that's what pdev expects.  It will
  1086.      * convert to a sprite value if needed.
  1087.      */
  1088.     return (status);
  1089. }
  1090.  
  1091.  
  1092. /*
  1093.  *----------------------------------------------------------------------
  1094.  *
  1095.  * MigPdev_CloseAllStreams --
  1096.  *
  1097.  *    Close all open client streams, and the stream for any existing
  1098.  *    pdev master.  This occurs when we fork a process
  1099.  *     to become the new global master: the child closes its streams.
  1100.  *
  1101.  * Results:
  1102.  *    None.
  1103.  *
  1104.  * Side effects:
  1105.  *    Memory for the client records is freed.
  1106.  *
  1107.  *----------------------------------------------------------------------
  1108.  */
  1109.  
  1110. void
  1111. MigPdev_CloseAllStreams()
  1112. {
  1113. #ifdef notdef
  1114.     List_Links *listPtr;
  1115.     Migd_OpenStreamInfo *cltPtr;
  1116.  
  1117.     while (!List_IsEmpty(openStreamList)) {
  1118.     listPtr = List_First(openStreamList);
  1119.     List_Remove(listPtr);
  1120.     cltPtr = (Migd_OpenStreamInfo *) listPtr;
  1121.     close(cltPtr->streamPtr->streamID);
  1122.     free(cltPtr);
  1123.     }
  1124. #endif
  1125.     if (pdev != (Pdev_Token) NULL) {
  1126.     Pdev_Close(pdev);
  1127.     }
  1128. }
  1129.